<?php

declare(strict_types=1);

namespace App\Service\Client;


use App\Constants\ContextKey;
use App\Constants\ErrorCode;
use App\Dao\CooperativeDao;
use App\Dao\UserDao;
use App\Dao\UserEmployerDao;
use App\Exception\BusinessException;
use App\Model\Cooperative;
use App\Model\User;
use App\Model\UserEmployer;
use App\Model\UserInfo;
use App\Utils\Jwt;
use App\Utils\Log;
use App\Utils\SMS;
use App\Utils\Wechat\OpenPlatform\MiniProgram;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Context;
use App\Constants\Model\User as UserConstants;
use App\Constants\Model\UserEmployer as UserEmployerConstants;
use App\Constants\Model\UserInfo as UserInfoConstants;


class LoginService extends BaseService
{

    /**
     * @Inject()
     * @var UserDao
     */
    protected $userDao;

    /**
     * @Inject()
     * @var UserEmployerDao
     */
    protected $userEmployerDao;

    /**
     * @Inject()
     * @var CooperativeDao
     */
    protected $cooperativeDao;

    protected function cooperativeInfo(): Cooperative
    {
        return Context::get(ContextKey::COOPERATIVE);
    }


    /**
     * 手机验证码登录-如果用户不存在则创建
     * @param array $data
     * @return array
     */
    public function loginUseCaptcha(array $data): array
    {
        $sms = di(SMS::class);
        $sms->checkCaptcha($data['phone'], $data['code']);

        /** @var User $user */
        $user = $this->userDao->first(
            [
                'cooperative_id' => $this->cooperativeInfo()->id,
                'phone' => $data['phone']
            ]
        );

        if ($user) {
            $result['code'] = $this->checkUserStatus($user);
        } else {
            $result['code'] = 1;

            Db::beginTransaction();
            try {
                $user = new User();
                $user->nickname = '用户' . $this->randString(10);
                $user->phone = $data['phone'];
                $user->cooperative_id = $this->cooperativeInfo()->id;
                $user->status = UserConstants::STATUS_UNBLOCK;
                $user->level = UserConstants::DEFAULT_LEVEL;
                $user->credit_point = UserConstants::DEFAULT_CREDIT_POINT;
                $user->save();

                $userInfo = new UserInfo();
                $userInfo->user_id = $user->id;
                $userInfo->sex = UserInfoConstants::SEX_HIDDEN;
                $userInfo->save();

                Db::commit();
            } catch (\Throwable $e) {
                Log::get()->error($e->getCode(), [$e->getMessage(), $data]);
                Log::get()->error($e->getTraceAsString());

                Db::rollBack();
                throw new BusinessException(ErrorCode::SYS_BUSY);
            }
        }
        $result['token'] = Jwt::token(['user_id' => $user->id]);

        return $result;
    }

    /**
     * 手机密码登录
     * @param array $data
     * @return array
     */
    public function loginUsePassword(array $data): array
    {
        /** @var User $user */
        $user = $this->userDao->first(
            [
                'cooperative_id' => $this->cooperativeInfo()->id,
                'phone' => $data['phone']
            ]
        );

        if (!$user) {
            throw new BusinessException(ErrorCode::USER_NOT_EXIST);
        }

        //密码错误
        if (!password_verify($data['password'], $user->password)) {
            throw new BusinessException(ErrorCode::USER_PASSWORD_FAIL);
        }

        $result['code'] = $this->checkUserStatus($user);
        $result['token'] = Jwt::token(['user_id' => $user->id]);

        return $result;
    }


    /**
     * 微信快捷登录
     * @param array $data
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function loginUseWx(array $data): array
    {
        /** @var Cooperative $cooperative */
        $cooperative = $this->cooperativeDao->first(['id' => $this->cooperativeInfo()->id]);
        if (!$cooperative) {
            throw new BusinessException(ErrorCode::DOMAIN_ERROR);
        }
        $miniProgram = di(MiniProgram::class);
        $wxInfo = $miniProgram->login($cooperative->wx_mp_appid, $data['code']);

        /** @var User $user */
        $user = $this->userDao->first(
            [
                'cooperative_id' => $this->cooperativeInfo()->id,
                'wx_mp_openid' => $wxInfo['openid']
            ]
        );


        if (!$user) {
            return [
                'state' => 'not_user',
                'openid' => $wxInfo['openid']
            ];
        }

        $result['code'] = $this->checkUserStatus($user);
        $result['status'] = 'login_success';
        $result['token'] = Jwt::token(['user_id' => $user->id]);
        return $result;
    }


    /**
     * 微信注册/绑定且登录
     * @param array $data
     * @return array
     */
    public function registerUseWx(array $data): array
    {
        $sms = di(SMS::class);
        $sms->checkCaptcha($data['phone'], $data['code']);

        /** @var User $user */
        $user = $this->userDao->first(['phone' => $data['phone'], 'cooperative_id' => $this->cooperativeInfo()->id]);
        if ($user) {
            $user->wx_mp_openid = $data['openid'];
            $user->save();
        } else {
            Db::beginTransaction();
            try {
                $user = new User();
                $user->nickname = '用户' . $this->randString(10);
                $user->phone = $data['phone'];
                $user->wx_mp_openid = $data['openid'];
                $user->cooperative_id = $this->cooperativeInfo()->id;
                $user->status = UserConstants::STATUS_UNBLOCK;
                $user->level = UserConstants::DEFAULT_LEVEL;
                $user->credit_point = UserConstants::DEFAULT_CREDIT_POINT;
                $user->save();

                $userInfo = new UserInfo();
                $userInfo->user_id = $user->id;
                $userInfo->sex = UserInfoConstants::SEX_HIDDEN;
                $userInfo->save();

                Db::commit();
            } catch (\Throwable $e) {
                Log::get()->error($e->getCode(), [$e->getMessage(), $data]);
                Log::get()->error($e->getTraceAsString());

                Db::rollBack();
                throw new BusinessException(ErrorCode::SYS_BUSY);
            }
        }
        return ['token' => Jwt::token(['user_id' => $user->id])];
    }


    /**
     * 检测用户状态
     * @param $user
     * @return int|string
     */
    private function checkUserStatus($user)
    {
        if ($user->status != UserConstants::STATUS_UNBLOCK) {
            //不是悬赏主
            if ($user->is_employer != UserConstants::IS_EMPLOYER_YES) {
                throw new BusinessException(ErrorCode::USER_DISABLE);
            }

            /** @var UserEmployer $userEmployer */
            $userEmployer = $this->userEmployerDao->first(['user_id' => $user->id]);
            //悬赏主数据不存在
            if (!$userEmployer) {
                throw new BusinessException(ErrorCode::USER_DISABLE);
            }

            //悬赏主被封
            if ($userEmployer->status != UserEmployerConstants::STATUS_UNBLOCK) {
                throw new BusinessException(ErrorCode::USER_DISABLE);
            }

            //悬赏主可用
            return ErrorCode::EMPLOYER_ENABLE;
//            throw new BusinessException(ErrorCode::EMPLOYER_ENABLE);
        }
        return 0;
    }


}